package com.nxy.cpfsfe.busi.unfyag;

import com.adtec.starring.datapool.CompSDO;
import com.adtec.starring.datapool.EPOper;
import com.adtec.starring.exception.BaseException;
import com.adtec.starring.struct.dta.DtaInfo;
import com.nxy.cpfsfe.PubBeanSerial;
import com.nxy.cpfsfe.enumtype.*;
import com.nxy.cpfsfe.service.CpfsService;
import com.nxy.cpfsfe.util.*;
import org.apache.commons.lang.StringUtils;
import org.dom4j.DocumentException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;

import java.sql.SQLException;
import java.util.Map;

/**
 * Description汇兑支付异步流程
 * Created by nxygyzd on 2019/11/25.
 */
public class RmPASrvBean implements CpfsService {
    private final static Logger LOGGER = LoggerFactory.getLogger(RmPASrvBean.class);

    @Override
    public void doService() {
        LOGGER.debug("---------汇兑支付异步流程开始---------");
        Map<String,String> map = null;
        String tpId = DtaInfo.getInstance().getTpId();
        // 获取输入
        CompSDO inputSdo = (CompSDO) EPOper.getCompSDO(tpId, "ReqBody"); // 获取输入接口
        try {
            String nginxUrl = (String)EPOper.get(tpId, "ReqBean[0].head[0].iPAddr");
            String bizMsg = (String) inputSdo.getValue("BizMsg")!=null?(String) inputSdo.getValue("BizMsg"):""; // 业务报文
            LOGGER.info("nginxUrl地址[{}],CPFS100业务报文：[{}]",nginxUrl,bizMsg);
            //生成业务map
            map = XmlUtil.xml2Map(bizMsg);
            //1、入库支付流水表
            String currentValue = null;
            PubBeanSerial pubBeanSerial = PubBeanSerial.getInstance();
            currentValue = pubBeanSerial.getSeqNoAndIncrea(TcSequenceEnum.CPFSSEQ.getCode());
            LOGGER.debug("currentValue流水号：[{}]",currentValue);
            map.put("currentValue", currentValue);
            map.put("NginxUrl",nginxUrl);
            //插入数据支付流水表TsPCmd
            pubBeanSerial.insertBySerivalMap(map);
            //2、组装3300报文并发送3300报文
            String rpsMsg = handleCBS3300(map);
            //4、解析3301响应结果
            handleRpsMsg(rpsMsg,map);
        }catch(DataAccessException e){
            int a =((SQLException) e.getCause()).getErrorCode();
            DBErrorCdEnum dberr = DBErrorCdEnum.getEnum(a+"");
            map.put("msg", dberr.getDesc());
            map.put("resultCode",dberr.getName());
            LOGGER.error("汇兑支付入库失败，失败原因[{}]",dberr.getDesc());
        }catch (BaseException e) {
            LOGGER.error("汇兑支付异步流程处理失败,错误码[{}],错误原因[{}]",e.getErrorCode(),e.getErrorDesc());
            LOGGER.error("错误信息栈",e);
            map.put("msg", e.getErrorDesc());
            map.put("resultCode",e.getErrorCode());
        }catch (Throwable e) {
            LOGGER.error("汇兑支付异步流程处理失败",e);
            map.put("msg", "汇兑支付异步流程处理失败");
            map.put("resultCode",RespCd.NCPO3999);
        }
        try {
            //判断是否主动发起501报文，只有失败的情况下发送
            if(StringUtils.isNotBlank( map.get("resultCode"))&&(!map.get("resultCode").startsWith("00"))){
                String bizMsgResult =  ResponseUtil.build501Xml(map);
                HttpUtil.responseSendJson(bizMsgResult,map);
            }
        } catch (BaseException e) {
            LOGGER.error("汇兑支付异步流程发送501报文失败，异常码[{}],错误信息[{}]",e.getErrorCode(),e.getErrorDesc());
            LOGGER.error("汇兑支付异步流程发送501报文失败",e);
        }catch (Throwable e) {
            LOGGER.error("汇兑支付异步流程发送501报文处理失败",e);
        }
        LOGGER.debug("---------汇兑支付异步流程处理完成---------");
    }

    /**
     * 处理3301响应报文
     * @param rpsMsg
     * @param map
     */
    private void handleRpsMsg(String rpsMsg, Map<String, String> map){
        //判断回执报文是否为空
        if(StringUtils.isNotBlank(rpsMsg)){
            Map<String,String> rpsmap = XmlUtil.xml2Map(rpsMsg);
            String  retCd = StringUtil.trimObject(rpsmap.get("/transaction/header/status/retCd"));
            //返回码前两位为00代表成功
            if(retCd.startsWith("00")&&retCd.length() ==6){
                    return ;
            }else{
                map.put("msg", StringUtil.trimObject(rpsmap.get("/transaction/header/status/desc")));
                map.put("resultCode",retCd);
            }
        }else{
            LOGGER.error("3301回执报文为空，请联系");
            map.put("msg", "3301回执报文为空，请联系");
            map.put("resultCode",RespCd.NCPO0005);
        }
    }

    /**
     * cbs报文组装并调用网关处理
     * @param map
     * @return
     */
    private String handleCBS3300(Map<String, String> map) {
        String tpId = DtaInfo.getInstance().getTpId();
        String rspMsg="";
        try{
            //组建3300报文
            String xmlCBS3300 = XmlCBSBuildUtil.buildXmlCBS3300(map);
            LOGGER.info("CBS3300报文[{}]",xmlCBS3300);
            EPOper.put(tpId, "ReqBean[0].head[0].rcvAppCd", SysEcodeEnum.PESB.getCode());
            EPOper.put(tpId, "ReqBean[0].head[0].reqServCd", MsgCdOrTpEnum.CBS_3300.getCode());
            EPOper.getCompSDO(tpId, "ReqBody").setValue("BizMsg", xmlCBS3300);
            rspMsg = RpcCommUtil.getInstance().rpcFeToGWRetMsg(tpId, RpcOutputInfoEnum.OutputName_Pub_Cpfsgw.getCode(),RpcOutputInfoEnum.OutPutSvr_CpfsFwdThrdPrtS.getCode());
        }catch(Exception e){
            LOGGER.error("调用网关转发NPS.365报文服务失败",e);
            throw new BaseException(RespCd.NCPO6047,e,"调用网关服务异常");
        }
        return rspMsg;
    }
}
